#!/bin/bash
#
# Varnish HTTPS配置脚本
# 使用Hitch作为SSL/TLS终止代理
#
# 使用方法：
#   sudo bash setup-varnish-https.sh
#

set -e

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 配置变量
DOMAIN="ws.waterism.tech"
HTTPS_PORT="6443"
VARNISH_PORT="6081"
EMAIL="gaoyu.ssdut@icloud.com"

echo -e "${GREEN}======================================${NC}"
echo -e "${GREEN}Varnish HTTPS配置脚本${NC}"
echo -e "${GREEN}======================================${NC}"
echo ""
echo "域名: $DOMAIN"
echo "HTTPS端口: $HTTPS_PORT"
echo "Varnish端口: $VARNISH_PORT"
echo ""

# 辅助函数：安全地设置证书文件权限
set_cert_permissions() {
    local cert_file="$1"
    chmod 600 "$cert_file"
    
    # 检查hitch用户是否存在
    if id "hitch" &>/dev/null; then
        chown hitch:hitch "$cert_file"
    else
        # Ubuntu可能使用不同的用户或不创建用户
        chown root:root "$cert_file"
    fi
}

# 检查是否为root用户
if [[ $EUID -ne 0 ]]; then
   echo -e "${RED}错误: 此脚本需要root权限运行${NC}"
   echo "请使用: sudo bash $0"
   exit 1
fi

# 检测操作系统
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
    VERSION=$VERSION_ID
else
    echo -e "${RED}无法检测操作系统${NC}"
    exit 1
fi

echo -e "${YELLOW}检测到操作系统: $OS $VERSION${NC}"
echo ""

# 1. 安装Hitch
echo -e "${GREEN}[1/7] 安装Hitch...${NC}"

if [[ "$OS" == "centos" ]] || [[ "$OS" == "rhel" ]]; then
    yum install -y epel-release
    yum install -y hitch
elif [[ "$OS" == "ubuntu" ]] || [[ "$OS" == "debian" ]]; then
    apt update
    apt install -y hitch
else
    echo -e "${RED}不支持的操作系统: $OS${NC}"
    exit 1
fi

# 验证安装
if ! command -v hitch &> /dev/null; then
    echo -e "${RED}Hitch安装失败${NC}"
    exit 1
fi

echo -e "${GREEN}Hitch安装成功: $(hitch --version)${NC}"
echo ""

# 2. 创建证书目录
echo -e "${GREEN}[2/7] 创建证书目录...${NC}"
mkdir -p /etc/hitch/certs
echo -e "${GREEN}证书目录创建成功${NC}"
echo ""

# 3. 检查并准备SSL证书
echo -e "${GREEN}[3/7] 准备SSL证书...${NC}"

CERT_PATH="/etc/letsencrypt/live/$DOMAIN"
HITCH_CERT="/etc/hitch/certs/$DOMAIN.pem"

if [ -d "$CERT_PATH" ]; then
    echo -e "${YELLOW}发现已存在的Let's Encrypt证书${NC}"
    
    # 合并证书和私钥
    cat "$CERT_PATH/fullchain.pem" "$CERT_PATH/privkey.pem" > "$HITCH_CERT"
    chmod 600 "$HITCH_CERT"
    
    # 检查hitch用户是否存在，不存在则使用root
    if id "hitch" &>/dev/null; then
        chown hitch:hitch "$HITCH_CERT"
    else
        echo -e "${YELLOW}注意: hitch用户不存在，使用root权限${NC}"
        chown root:root "$HITCH_CERT"
    fi
    
    echo -e "${GREEN}证书合并成功${NC}"
else
    echo -e "${YELLOW}未找到证书，需要申请新证书${NC}"
    echo ""
    echo "请选择证书申请方式:"
    echo "1) DNS验证（推荐，无需开放80端口）"
    echo "2) HTTP验证（需要临时开放80端口）"
    echo "3) 跳过证书申请（手动配置）"
    read -p "请选择 [1-3]: " choice
    
    case $choice in
        1)
            echo -e "${YELLOW}开始DNS验证方式申请证书...${NC}"
            certbot certonly --manual \
                --preferred-challenges dns \
                -d "$DOMAIN" \
                --email "$EMAIL" \
                --agree-tos \
                --no-eff-email
            
            if [ $? -eq 0 ]; then
                cat "$CERT_PATH/fullchain.pem" "$CERT_PATH/privkey.pem" > "$HITCH_CERT"
                set_cert_permissions "$HITCH_CERT"
                echo -e "${GREEN}证书申请成功${NC}"
            else
                echo -e "${RED}证书申请失败${NC}"
                exit 1
            fi
            ;;
        2)
            echo -e "${YELLOW}开始HTTP验证方式申请证书...${NC}"
            echo -e "${YELLOW}注意: 需要临时停止占用80端口的服务${NC}"
            
            certbot certonly --standalone \
                -d "$DOMAIN" \
                --email "$EMAIL" \
                --agree-tos \
                --no-eff-email
            
            if [ $? -eq 0 ]; then
                cat "$CERT_PATH/fullchain.pem" "$CERT_PATH/privkey.pem" > "$HITCH_CERT"
                set_cert_permissions "$HITCH_CERT"
                echo -e "${GREEN}证书申请成功${NC}"
            else
                echo -e "${RED}证书申请失败${NC}"
                exit 1
            fi
            ;;
        3)
            echo -e "${YELLOW}跳过证书申请${NC}"
            echo "请手动将证书放置到: $HITCH_CERT"
            echo "格式: 证书+私钥合并的PEM文件"
            exit 0
            ;;
        *)
            echo -e "${RED}无效的选择${NC}"
            exit 1
            ;;
    esac
fi

echo ""

# 4. 配置Hitch
echo -e "${GREEN}[4/7] 配置Hitch...${NC}"

# 检查是否需要用户配置
HITCH_USER_CONFIG=""
if id "hitch" &>/dev/null; then
    HITCH_USER_CONFIG="user = \"hitch\"
group = \"hitch\""
    echo -e "${GREEN}使用hitch用户运行${NC}"
else
    echo -e "${YELLOW}hitch用户不存在，使用root运行${NC}"
fi

cat > /etc/hitch/hitch.conf <<EOF
# Hitch配置文件
# HTTPS终止代理，转发到Varnish

# 监听地址和端口
frontend = "[*]:$HTTPS_PORT"

# 后端Varnish地址
backend = "[127.0.0.1]:$VARNISH_PORT"

# SSL/TLS证书文件
pem-file = "$HITCH_CERT"

# 性能和安全配置
workers = 4
backlog = 1000
keepalive = 3600

# TLS协议版本
tls-protos = TLSv1.2 TLSv1.3

# 加密套件
ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"

prefer-server-ciphers = on

# ALPN协议支持
alpn-protos = "h2,http/1.1"

# 日志配置
syslog = on
syslog-facility = "daemon"

# 用户和组（如果存在）
$HITCH_USER_CONFIG

EOF

echo -e "${GREEN}Hitch配置完成${NC}"
echo ""

# 5. 配置防火墙
echo -e "${GREEN}[5/7] 配置防火墙...${NC}"

if command -v firewall-cmd &> /dev/null; then
    # CentOS/RHEL使用firewalld
    firewall-cmd --permanent --add-port=$HTTPS_PORT/tcp
    firewall-cmd --reload
    echo -e "${GREEN}防火墙配置完成 (firewalld)${NC}"
elif command -v ufw &> /dev/null; then
    # Ubuntu使用ufw
    ufw allow $HTTPS_PORT/tcp
    echo -e "${GREEN}防火墙配置完成 (ufw)${NC}"
else
    echo -e "${YELLOW}未检测到防火墙，请手动开放端口 $HTTPS_PORT${NC}"
fi

echo ""

# 6. 配置证书自动续期
echo -e "${GREEN}[6/7] 配置证书自动续期...${NC}"

# 创建续期脚本
cat > /usr/local/bin/hitch-cert-renew.sh <<'EOF'
#!/bin/bash
# Hitch证书续期脚本

DOMAIN="ws.waterism.tech"
CERT_PATH="/etc/letsencrypt/live/$DOMAIN"
HITCH_CERT="/etc/hitch/certs/$DOMAIN.pem"

# 合并新证书
cat "$CERT_PATH/fullchain.pem" "$CERT_PATH/privkey.pem" > "$HITCH_CERT"

# 设置权限
chmod 600 "$HITCH_CERT"

# 根据用户是否存在设置所有者
if id "hitch" &>/dev/null; then
    chown hitch:hitch "$HITCH_CERT"
else
    chown root:root "$HITCH_CERT"
fi

# 重启Hitch
systemctl reload hitch

# 记录日志
echo "$(date): Hitch certificate renewed" >> /var/log/hitch-cert-renew.log
EOF

chmod +x /usr/local/bin/hitch-cert-renew.sh

# 创建cron任务
cat > /etc/cron.d/certbot-renew-hitch <<EOF
# 每天凌晨2点检查证书续期
0 2 * * * root certbot renew --quiet --deploy-hook "/usr/local/bin/hitch-cert-renew.sh"
EOF

echo -e "${GREEN}证书自动续期配置完成${NC}"
echo ""

# 7. 启动服务
echo -e "${GREEN}[7/7] 启动服务...${NC}"

# 首先确保Varnish正在运行（Hitch的后端）
echo "检查Varnish服务..."
if systemctl is-active --quiet varnish; then
    echo -e "${GREEN}✓ Varnish已在运行${NC}"
else
    echo -e "${YELLOW}启动Varnish服务...${NC}"
    systemctl restart varnish
    sleep 2
    
    if systemctl is-active --quiet varnish; then
        echo -e "${GREEN}✓ Varnish启动成功${NC}"
    else
        echo -e "${RED}✗ Varnish启动失败${NC}"
        echo "Hitch需要Varnish作为后端，请先修复Varnish"
        echo "查看日志: journalctl -u varnish -n 50"
        exit 1
    fi
fi

# 验证Varnish端口监听
sleep 1
if netstat -tlnp 2>/dev/null | grep ":$VARNISH_PORT" || ss -tlnp 2>/dev/null | grep ":$VARNISH_PORT"; then
    echo -e "${GREEN}✓ Varnish正在监听端口 $VARNISH_PORT${NC}"
else
    echo -e "${RED}✗ Varnish未在端口 $VARNISH_PORT 上监听${NC}"
    echo "Hitch无法连接到后端，请检查Varnish配置"
    exit 1
fi

# 测试Hitch配置
echo ""
echo "测试Hitch配置..."
if hitch --config=/etc/hitch/hitch.conf --test; then
    echo -e "${GREEN}✓ Hitch配置测试通过${NC}"
else
    echo -e "${RED}✗ Hitch配置测试失败${NC}"
    echo "请检查配置文件: /etc/hitch/hitch.conf"
    echo "或运行诊断脚本: bash scripts/diagnose-varnish-https.sh"
    exit 1
fi

# 启动Hitch
echo ""
echo "启动Hitch服务..."
systemctl enable hitch
systemctl restart hitch

# 等待服务启动
sleep 3

if systemctl is-active --quiet hitch; then
    echo -e "${GREEN}✓ Hitch服务运行正常${NC}"
else
    echo -e "${RED}✗ Hitch服务启动失败${NC}"
    echo ""
    echo "查看详细日志:"
    echo "  journalctl -u hitch -n 50"
    echo "  systemctl status hitch"
    echo ""
    echo "运行诊断脚本:"
    echo "  bash scripts/diagnose-varnish-https.sh"
    exit 1
fi

if systemctl is-active --quiet varnish; then
    echo -e "${GREEN}✓ Varnish服务运行正常${NC}"
else
    echo -e "${RED}✗ Varnish服务未运行${NC}"
    echo "查看日志: journalctl -u varnish -n 50"
    exit 1
fi

echo ""

# 显示端口监听状态
echo -e "${GREEN}端口监听状态:${NC}"
netstat -tlnp | grep -E "$VARNISH_PORT|$HTTPS_PORT" || ss -tlnp | grep -E "$VARNISH_PORT|$HTTPS_PORT"
echo ""

# 测试HTTPS连接
echo -e "${GREEN}测试HTTPS连接...${NC}"
sleep 1

if curl -s -o /dev/null -w "%{http_code}" --max-time 5 "https://$DOMAIN:$HTTPS_PORT/" > /dev/null 2>&1; then
    echo -e "${GREEN}✓ HTTPS连接测试成功${NC}"
else
    echo -e "${YELLOW}⚠ HTTPS连接测试失败（可能需要等待DNS生效）${NC}"
fi

echo ""
echo -e "${GREEN}======================================${NC}"
echo -e "${GREEN}配置完成！${NC}"
echo -e "${GREEN}======================================${NC}"
echo ""
echo -e "${GREEN}访问地址:${NC}"
echo "  HTTPS: https://$DOMAIN:$HTTPS_PORT/"
echo "  HTTP:  http://$DOMAIN:$VARNISH_PORT/ (如果开放)"
echo ""
echo -e "${GREEN}管理命令:${NC}"
echo "  查看Hitch状态:    systemctl status hitch"
echo "  查看Varnish状态:  systemctl status varnish"
echo "  查看Hitch日志:    journalctl -u hitch -f"
echo "  查看Varnish日志:  varnishlog"
echo "  重启Hitch:        systemctl restart hitch"
echo "  重启Varnish:      systemctl restart varnish"
echo ""
echo -e "${YELLOW}注意事项:${NC}"
echo "  1. 如果使用云服务器，请在安全组开放 $HTTPS_PORT 端口"
echo "  2. 证书有效期90天，已配置自动续期"
echo "  3. 查看完整文档: docs/服务器端/Varnish配置HTTPS指南.md"
echo ""

